home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / net / ds3100.md / netLE.c < prev    next >
C/C++ Source or Header  |  1991-02-12  |  15KB  |  577 lines

  1. /* 
  2.  * netLE.c --
  3.  *
  4.  *    The main routines for the device driver for the AMD 7990 Ethernet 
  5.  *    Controller.
  6.  *
  7.  * Copyright (C) 1989 Digital Equipment Corporation.
  8.  * Permission to use, copy, modify, and distribute this software and
  9.  * its documentation for any purpose and without fee is hereby granted,
  10.  * provided that the above copyright notice appears in all copies.  
  11.  * Digital Equipment Corporation makes no representations about the
  12.  * suitability of this software for any purpose.  It is provided "as is"
  13.  * without express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /sprite/src/kernel/net/ds3100.md/RCS/netLE.c,v 9.4 91/02/12 14:15:20 jhh Exp $ SPRITE (DECWRL)";
  18. #endif not lint
  19.  
  20. #include <netInt.h>
  21. #include <sprite.h>
  22. #include <sys.h>
  23. #include <list.h>
  24. #include <vm.h>
  25. #include <vmMach.h>
  26. #include <mach.h>
  27. #include <netLEInt.h>
  28. #include <machAddrs.h>
  29. #include <assert.h>
  30.  
  31. Address    NetLEMemAlloc();
  32.  
  33. NetLEState    netLEDebugState;
  34.  
  35.  
  36. /*
  37.  *----------------------------------------------------------------------
  38.  *
  39.  * NetLEInit --
  40.  *
  41.  *    Initialize the LANCE AMD 7990 Ethernet chip.
  42.  *
  43.  * Results:
  44.  *    SUCCESS if the LANCE controller was found and initialized,
  45.  *    FAILURE otherwise.
  46.  *
  47.  * Side effects:
  48.  *    Initializes the netEtherFuncs record, as well as the chip.
  49.  *
  50.  *----------------------------------------------------------------------
  51.  */
  52. ReturnStatus
  53. NetLEInit(interPtr)
  54.     Net_Interface    *interPtr;     /* Network interface. */
  55. {
  56.     Address         ctrlAddr;/* Kernel virtual address of controller. */
  57.     int         i;
  58.     List_Links        *itemPtr;
  59.     NetLEState        *statePtr;
  60.     char        buffer[32];
  61.  
  62.     assert(sizeof(NetLE_Reg) == 4);
  63.  
  64.     DISABLE_INTR();
  65.  
  66.     ctrlAddr = interPtr->ctrlAddr;
  67.     /*
  68.      * If the address is physical (not in kernel's virtual address space)
  69.      * then we have to map it in.
  70.      */
  71.     if (interPtr->virtual == FALSE) {
  72.     printf("NetLEInit: ds3100 does not support mapping in devices yet.\n");
  73.     printf("NetLEInit: can't map in network device at 0x%x\n", ctrlAddr);
  74.     return FAILURE;
  75. #if 0
  76.     ctrlAddr = (char *) VmMach_MapInDevice(ctrlAddr, 1);
  77. #endif
  78.     }
  79.     statePtr = (NetLEState *) malloc (sizeof(NetLEState));
  80.     statePtr->running = FALSE;
  81.  
  82.     /*
  83.      * The onboard control register is at a pre-defined kernel virtual
  84.      * address.
  85.      */
  86.     statePtr->regDataPortPtr = (unsigned short *)MACH_NETWORK_INTERFACE_ADDR;
  87.     statePtr->regAddrPortPtr = statePtr->regDataPortPtr + 2;
  88.     {
  89.     /*
  90.      * Poke the controller by setting the RAP.
  91.      */
  92.     short value = NET_LE_CSR0_ADDR;
  93.     ReturnStatus status;
  94.     status = Mach_Probe(sizeof(short), (char *) &value, 
  95.               (char *) statePtr->regAddrPortPtr);
  96.     if (status != SUCCESS) {
  97.         /*
  98.          * Got a bus error.
  99.          */
  100.         free((char *) statePtr);
  101.         ENABLE_INTR();
  102.         return(FAILURE);
  103.     }
  104.     }
  105.     Mach_SetHandler(interPtr->vector, Net_Intr, (ClientData) interPtr);
  106.     /*
  107.      * Initialize the transmission list.  
  108.      */
  109.     statePtr->xmitList = &statePtr->xmitListHdr;
  110.     List_Init(statePtr->xmitList);
  111.  
  112.     statePtr->xmitFreeList = &statePtr->xmitFreeListHdr;
  113.     List_Init(statePtr->xmitFreeList);
  114.  
  115.     for (i = 0; i < NET_LE_NUM_XMIT_ELEMENTS; i++) {
  116.     itemPtr = (List_Links *) malloc(sizeof(NetXmitElement)), 
  117.     List_InitElement(itemPtr);
  118.     List_Insert(itemPtr, LIST_ATREAR(statePtr->xmitFreeList));
  119.     }
  120.  
  121.     Mach_GetEtherAddress(&statePtr->etherAddress);
  122.     (void) Net_EtherAddrToString(&statePtr->etherAddress, buffer);
  123.     printf("%s-%d Ethernet address %s\n", interPtr->name, interPtr->number, 
  124.         buffer);
  125.     /*
  126.      * Allocate the initialization block.
  127.      */
  128.     statePtr->initBlockPtr = NetLEMemAlloc(NET_LE_INIT_SIZE, TRUE);
  129.  
  130.     interPtr->init    = NetLEInit;
  131.     interPtr->output     = NetLEOutput;
  132.     interPtr->intr    = NetLEIntr;
  133.     interPtr->reset     = NetLERestart;
  134.     interPtr->getStats    = NetLEGetStats;
  135.     interPtr->netType    = NET_NETWORK_ETHER;
  136.     interPtr->maxBytes    = NET_ETHER_MAX_BYTES - sizeof(Net_EtherHdr);
  137.     interPtr->minBytes    = 0;
  138.     interPtr->interfaceData = (ClientData) statePtr;
  139.     NET_ETHER_ADDR_COPY(statePtr->etherAddress, 
  140.     interPtr->netAddress[NET_PROTO_RAW].ether);
  141.     interPtr->broadcastAddress.ether = netEtherBroadcastAddress.ether;
  142.     interPtr->flags |= NET_IFLAGS_BROADCAST;
  143.     statePtr->interPtr = interPtr;
  144.     statePtr->recvMemInitialized = FALSE;
  145.     statePtr->recvMemAllocated = FALSE;
  146.     statePtr->xmitMemInitialized = FALSE;
  147.     statePtr->xmitMemAllocated = FALSE;
  148.  
  149.  
  150.     /*
  151.      * Reset the world.
  152.      */
  153.     NetLEReset(interPtr);
  154.  
  155.     /*
  156.      * Now we are running.
  157.      */
  158.  
  159.     statePtr->running = TRUE;
  160.     ENABLE_INTR();
  161.     return (SUCCESS);
  162. }
  163.  
  164.  
  165. /*
  166.  *----------------------------------------------------------------------
  167.  *
  168.  * NetLEReset --
  169.  *
  170.  *    Reset the world.
  171.  *
  172.  * Results:
  173.  *    None.
  174.  *
  175.  * Side effects:
  176.  *    All of the pointers in the netLEState structure are initialized.
  177.  *
  178.  *----------------------------------------------------------------------
  179.  */
  180. void
  181. NetLEReset(interPtr)
  182.     Net_Interface    *interPtr; /* Interface to reset. */
  183. {
  184.     NetLEState        *statePtr;
  185.     unsigned        addr;
  186.     int            i;
  187.  
  188.     statePtr = (NetLEState *) interPtr->interfaceData;
  189.     /* 
  190.      * Reset (and stop) the chip.
  191.      */
  192.     *statePtr->regAddrPortPtr = NET_LE_CSR0_ADDR;
  193.     *statePtr->regDataPortPtr = NET_LE_CSR0_STOP; 
  194.  
  195.     /*
  196.      * Set up the receive and transmit rings. 
  197.      */
  198.      NetLERecvInit(statePtr);
  199.      NetLEXmitInit(statePtr);
  200.  
  201.     /*
  202.      * Zero out the mode word.
  203.      */
  204.     *BUF_TO_ADDR(statePtr->initBlockPtr,NET_LE_INIT_MODE)=0;
  205.     /*
  206.      * Insert the ethernet address.
  207.      */
  208.     *BUF_TO_ADDR(statePtr->initBlockPtr, 
  209.               NET_LE_INIT_ETHER_ADDR) = 
  210.             (unsigned char)statePtr->etherAddress.byte1 |
  211.             ((unsigned char)statePtr->etherAddress.byte2 << 8);
  212.     *BUF_TO_ADDR(statePtr->initBlockPtr, 
  213.               NET_LE_INIT_ETHER_ADDR + 2) = 
  214.             (unsigned char)statePtr->etherAddress.byte3 | 
  215.             ((unsigned char)statePtr->etherAddress.byte4 << 8);
  216.     *BUF_TO_ADDR(statePtr->initBlockPtr, 
  217.             NET_LE_INIT_ETHER_ADDR + 4) = 
  218.             (unsigned char)statePtr->etherAddress.byte5 | 
  219.             ((unsigned char)statePtr->etherAddress.byte6 << 8);
  220.     /*
  221.      * Reject all multicast addresses.
  222.      */
  223.     for (i = 0; i < 4; i++) {
  224.     *BUF_TO_ADDR(statePtr->initBlockPtr, 
  225.               NET_LE_INIT_MULTI_MASK + (sizeof(short) * i)) = 0;
  226.     }
  227.     /*
  228.      * We want to get boot multicasts.
  229.      * These are addr ab-00-00-01-00-00 = hash bit 31?
  230.      */
  231.     *BUF_TO_ADDR(statePtr->initBlockPtr, NET_LE_INIT_MULTI_MASK) = 0x8000;
  232.  
  233.     /*
  234.      * Set up the receive ring pointer.
  235.      */
  236.     addr = BUF_TO_CHIP_ADDR(statePtr->recvDescFirstPtr);
  237.     *BUF_TO_ADDR(statePtr->initBlockPtr, NET_LE_INIT_RECV_LOW) = addr & 0xffff;
  238.     *BUF_TO_ADDR(statePtr->initBlockPtr, NET_LE_INIT_RECV_HIGH) =
  239.                 (unsigned)((addr >> 16) & 0xff) |
  240.         ((unsigned)((NET_LE_NUM_RECV_BUFFERS_LOG2 << 5) & 0xe0) << 8);
  241.     if (*BUF_TO_ADDR(statePtr->initBlockPtr,
  242.                   NET_LE_INIT_RECV_LOW) & 0x07) {
  243.     printf("netLE: Receive list not on QUADword boundary\n");
  244.     return;
  245.     }
  246.  
  247.     /*
  248.      * Set up the transmit ring pointer.
  249.      */
  250.     addr = BUF_TO_CHIP_ADDR(statePtr->xmitDescFirstPtr);
  251.     *BUF_TO_ADDR(statePtr->initBlockPtr, NET_LE_INIT_XMIT_LOW) = addr & 0xffff;
  252.     *BUF_TO_ADDR(statePtr->initBlockPtr, NET_LE_INIT_XMIT_HIGH) =
  253.                 (unsigned)((addr >> 16) & 0xff) |
  254.         ((unsigned)((NET_LE_NUM_XMIT_BUFFERS_LOG2 << 5) & 0xe0) << 8);
  255.     if (*BUF_TO_ADDR(statePtr->initBlockPtr, NET_LE_INIT_XMIT_LOW) & 0x07) {
  256.     printf("netLE: Transmit list not on QUADword boundary\n");
  257.     return;
  258.     }
  259.  
  260.     /*
  261.      * Clear the Bus master control register (csr3).
  262.      */
  263.     *statePtr->regAddrPortPtr = NET_LE_CSR3_ADDR;
  264.     *statePtr->regDataPortPtr = 0;
  265.  
  266.     /*
  267.      * Set the init block pointer address in csr1 and csr2
  268.      */
  269.     addr = BUF_TO_CHIP_ADDR(statePtr->initBlockPtr);
  270.     *statePtr->regAddrPortPtr = NET_LE_CSR1_ADDR;
  271.     *statePtr->regDataPortPtr = (short)(addr & 0xffff);
  272.  
  273.     *statePtr->regAddrPortPtr = NET_LE_CSR2_ADDR;
  274.     *statePtr->regDataPortPtr = (short)((addr >> 16) & 0xff);
  275.  
  276.     /*
  277.      * Tell the chip to initialize and wait for results.
  278.      */
  279.     *statePtr->regAddrPortPtr = NET_LE_CSR0_ADDR;
  280.     *statePtr->regDataPortPtr = NET_LE_CSR0_INIT | NET_LE_CSR0_INIT_DONE;
  281.  
  282.     {
  283.     int    i;
  284.     volatile unsigned short *csr0Ptr = statePtr->regDataPortPtr;
  285.  
  286.  
  287.     for (i = 0; ((*csr0Ptr & NET_LE_CSR0_INIT_DONE) == 0); i++) {
  288.         if (i > 50000) {
  289.         panic( "LE ethernet: Chip will not initialize.\n");
  290.         }
  291.     }
  292.  
  293.     /*
  294.      * Ack the interrupt.
  295.      */
  296.      *csr0Ptr = NET_LE_CSR0_INIT_DONE;
  297.     }
  298.  
  299.     /*
  300.      * Start the chip and enable interrupts.
  301.      */
  302.     *statePtr->regDataPortPtr = 
  303.             (NET_LE_CSR0_START | NET_LE_CSR0_INTR_ENABLE);
  304.  
  305.     printf("LE ethernet: Reinitialized chip.\n");
  306.     interPtr->flags |= NET_IFLAGS_RUNNING;
  307.  
  308. }
  309.  
  310.  
  311. /*
  312.  *----------------------------------------------------------------------
  313.  *
  314.  * NetLERestart --
  315.  *
  316.  *    Reinitialize the LANCE Ethernet chip.
  317.  *
  318.  * Results:
  319.  *    None.
  320.  *
  321.  * Side effects:
  322.  *    None.
  323.  *
  324.  *----------------------------------------------------------------------
  325.  */
  326. void
  327. NetLERestart(interPtr)
  328.     Net_Interface    *interPtr;     /* Interface to restart. */
  329. {
  330.     NetLEState    *statePtr = (NetLEState *) interPtr->interfaceData;
  331.  
  332.     DISABLE_INTR();
  333.  
  334.     /*
  335.      * Drop the current packet so the sender does't get hung.
  336.      */
  337.     NetLEXmitDrop(statePtr);
  338.  
  339.     /*
  340.      * Reset the world.
  341.      */
  342.     NetLEReset(interPtr);
  343.  
  344.     /*
  345.      * Restart transmission of packets.
  346.      */
  347.     NetLEXmitRestart(statePtr);
  348.  
  349.     ENABLE_INTR();
  350. }
  351.  
  352.  
  353. /*
  354.  *----------------------------------------------------------------------
  355.  *
  356.  * NetLEIntr --
  357.  *
  358.  *    Process an interrupt from the LANCE chip.
  359.  *
  360.  * Results:
  361.  *    None.
  362.  *
  363.  * Side effects:
  364.  *    None.
  365.  *
  366.  *----------------------------------------------------------------------
  367.  */
  368. void
  369. NetLEIntr(interPtr, polling)
  370.     Net_Interface    *interPtr;    /* Network interface.*/
  371.     Boolean    polling;        /* TRUE if are being polled instead of
  372.                      * processing an interrupt. */
  373. {
  374.     volatile register    NetLEState    *statePtr;
  375.     ReturnStatus        statusXmit, statusRecv;
  376.     register unsigned short    csr0;
  377.     Boolean            reset;
  378.  
  379.     statePtr = (NetLEState *) interPtr->interfaceData;
  380.     *statePtr->regAddrPortPtr = NET_LE_CSR0_ADDR;
  381.     csr0 = *statePtr->regDataPortPtr;
  382.  
  383.     /*
  384.      * Check for errors.
  385.      */
  386.  
  387.     if (csr0 & NET_LE_CSR0_ERROR) {
  388.     reset = TRUE;
  389.     if (csr0 & NET_LE_CSR0_MISSED_PACKET) {
  390.         printf("LE ethernet: Missed a packet.\n");
  391.         /*
  392.          * Clear interrupt bit but don't reset controller.
  393.          */
  394.         *statePtr->regDataPortPtr = NET_LE_CSR0_MISSED_PACKET;
  395.         reset = FALSE;
  396.     }
  397.     if (csr0 & NET_LE_CSR0_COLLISION_ERROR) {
  398.         /*
  399.          * Late collision error appear to happen when the machine
  400.          * is disconnected from the transceiver. When this happens
  401.          * we will complain about Lost of Carrier so the late
  402.          * collision message is uncessary.
  403.          *
  404.          * printf("LE ethernet: Late collision.\n");
  405.          */
  406.         reset = FALSE;
  407.     }
  408.     /*
  409.      * Check for fatal errors.  Kill the machine if we start babbling 
  410.      * (sending oversize ethernet packets). 
  411.      */
  412.     if (csr0 & NET_LE_CSR0_BABBLE) {
  413.         panic("LE ethernet: Transmit babble.\n");
  414.     }
  415.     if (csr0 & NET_LE_CSR0_MEMORY_ERROR) {
  416.         panic("LE ethernet: Memory Error.\n");
  417.     }
  418.     /*
  419.      * Clear the error the easy way, reinitialize everything.
  420.      */
  421.     if (reset == TRUE) {
  422.         NetLERestart(interPtr);
  423.         return;
  424.     }
  425.     }
  426.  
  427.     statusRecv = statusXmit = SUCCESS;
  428.     /*
  429.      * Did we receive a packet.
  430.      */
  431.     if (csr0 & NET_LE_CSR0_RECV_INTR) {
  432.     statusRecv = NetLERecvProcess(FALSE, statePtr);
  433.     }
  434.     /*
  435.      * Did we transmit a packet.
  436.      */
  437.     if (csr0 & NET_LE_CSR0_XMIT_INTR) {
  438.     statusXmit = NetLEXmitDone(statePtr);
  439.     }
  440.     /*
  441.      * Did the chip magically initialize itself?
  442.      */
  443.     if (csr0 & NET_LE_CSR0_INIT_DONE) {
  444.     printf( "LE ethernet: Chip initialized itself!!\n");
  445.     /*
  446.      * Better initialize it the way we want it.
  447.      */
  448.     statusRecv = FAILURE;
  449.     }
  450.  
  451.     if (statusRecv != SUCCESS || statusXmit != SUCCESS) {
  452.     NetLERestart(interPtr);
  453.     return;
  454.     }
  455.     /*
  456.      * If interrupts aren't enabled or there is no interrupt pending, then
  457.      * what are we doing here?
  458.      */
  459.  
  460.     if ( !(csr0 & NET_LE_CSR0_INTR_ENABLE) || !(csr0 & NET_LE_CSR0_INTR) ) {
  461.     /*
  462.      * We could be polling; that's why we were here.
  463.      */
  464.     if (!polling) {
  465.         printf("LE ethernet: Spurious interrupt CSR0 = <%x>\n", csr0);
  466.     } 
  467.     } 
  468.     return;
  469.  
  470. }
  471.  
  472. unsigned    bufAddr = MACH_NETWORK_BUFFER_ADDR;
  473.  
  474. /*
  475.  *----------------------------------------------------------------------
  476.  *
  477.  * NetLEMemAlloc -- 
  478.  *
  479.  *    Allocate memory from the buffer.
  480.  *
  481.  * Results:
  482.  *    None.
  483.  *
  484.  * Side effects:
  485.  *    None.
  486.  *
  487.  *----------------------------------------------------------------------
  488.  */
  489. Address
  490. NetLEMemAlloc(numBytes, wordAlign)
  491.     unsigned int    numBytes;
  492.     Boolean        wordAlign;
  493. {
  494.     Address    retVal;
  495.  
  496.     if (wordAlign) {
  497.     bufAddr &= ~0x3;
  498.     } else {
  499.     bufAddr &= ~0xf;
  500.     }
  501.     retVal = (Address)bufAddr;
  502.     bufAddr += numBytes * 2;
  503.  
  504.     return(retVal);
  505. }
  506.  
  507. #ifdef notdef
  508.  
  509. /*
  510.  *----------------------------------------------------------------------
  511.  *
  512.  * BUF_TO_CHIP_ADDR -- 
  513.  *
  514.  *    Convert a memory buffer address to an address for the chip.  
  515.  *
  516.  *    NOTE: This used to a macro but was changed to C for debugging
  517.  *          purposes, hence the weird name.  Should probably change back
  518.  *          to a macro.
  519.  *
  520.  * Results:
  521.  *    None.
  522.  *
  523.  * Side effects:
  524.  *    None.
  525.  *
  526.  *----------------------------------------------------------------------
  527.  */
  528. unsigned
  529. BUF_TO_CHIP_ADDR(addr)
  530.     Address    addr;
  531. {
  532.     int    off, base, tmp;
  533.     int    retAddr;
  534.  
  535.     off = (int)addr & NET_LE_DMA_CHIP_ADDR_MASK;
  536.     base = (int)NET_LE_DMA_BUFFER_ADDR;
  537.     tmp = off / 2;
  538.     if (off == tmp * 2) {
  539.     retAddr = base + tmp;
  540.     } else {
  541.     printf("BUF_TO_CHIP_ADDR: odd offset\n");
  542.     retAddr = base + tmp + 1;
  543.     }
  544.     return(retAddr);
  545. }
  546. #endif
  547.  
  548. /*
  549.  *----------------------------------------------------------------------
  550.  *
  551.  * NetLEGetStats --
  552.  *
  553.  *    Return the statistics for the interface.
  554.  *
  555.  * Results:
  556.  *    A pointer to the statistics structure.
  557.  *
  558.  * Side effects:
  559.  *    None.
  560.  *
  561.  *----------------------------------------------------------------------
  562.  */
  563.  
  564. ReturnStatus
  565. NetLEGetStats(interPtr, statPtr)
  566.     Net_Interface    *interPtr;        /* Current interface. */
  567.     Net_Stats        *statPtr;        /* Statistics to return. */
  568. {
  569.     NetLEState    *statePtr;
  570.     statePtr = (NetLEState *) interPtr->interfaceData;
  571.     DISABLE_INTR();
  572.     statPtr->ether = statePtr->stats;
  573.     ENABLE_INTR();
  574.     return SUCCESS;
  575. }
  576.  
  577.